const url = require('url')
const querystring = require('querystring')
const crypto = require('crypto')
const events = require('events')
const emitter = new events.EventEmitter()
const xml2js = require('xml2js')
const https = require('https')
const FormData = require('form-data')
const fs = require('fs')
const log = require('./log')
const getHtml = require('./getHtml')
const getClass = require('../../lib/getClass')
const logger = require('log4js').getLogger()

var instances = [];

var Wechat = function(obj) {
    if (!(this instanceof Wechat)) {
        for (var i = 0; i < instances.length; i++) {
            var same = true
            for (var key in obj) {
                if (key != 'access_token' && key != 'res' && obj[key] != instances[i][key]) {
                    same = false
                    break
                }
            }
            if (same) {
                return instances[i]
            }
        }
        return new Wechat(obj);
    }
    this.token = obj.token || '';
    this.access_token = obj.access_token || '';
    this.CorpID = obj.CorpID || '';
    this.Secret = obj.Secret || '';
    this.AppID = obj.AppID || '';
    this.AppSecret = obj.AppSecret || '';
    this.res = null;
    this.CorpID && this.Secret && this.gettoken().then(() => {}, () => {})
    this.AppID && this.AppSecret && this.gettoken().then(() => {}, () => {})
    instances.push(this)
}

//检验 token
Wechat.prototype.checkSignature = function(req, res) {
    if (req.method === 'GET') {
        var queryObj = querystring.parse(url.parse(req.url).query);
        var signature = queryObj.signature,
            timestamp = queryObj.timestamp,
            nonce = queryObj.nonce,
            echostr = queryObj.echostr,
            msg_signature = queryObj.msg_signature;

        var sha1 = crypto.createHash('sha1'),
            sha1Str = sha1.update([this.token, timestamp, nonce].sort().join('')).digest('hex');

        res.writeHead(200, {
            'Content-Type': 'text/plain'
        });
        res.end((sha1Str === signature) ? echostr : '');
        return res;
    }
}

//预处理器
Wechat.prototype.handler = function(req, res) {
    var xml = '';
    var self = this;
    self.res = res;

    req.setEncoding('utf8');
    req.on('data', function(chunk) {
        xml += chunk;
    });

    return new Promise(resolve => {
        req.on('end', function() {
            resolve(self.toJSON(xml))
        });
    })

    /**
     * clear all listening events to avoid repeat triggers
     */
    emitter.removeAllListeners('text');
    emitter.removeAllListeners('voice');
    emitter.removeAllListeners('event');
}

//解析器
//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140453
//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140454
Wechat.prototype.toJSON = function(xml) {
    var msg = {};
    xml2js.parseString(xml, function(err, result) {
        if (err) {
            logger.error('[' + __filename + ':' + __line + ']', err)
            return msg
        }
        var data = result.xml;

        msg.ToUserName = data.ToUserName[0];
        msg.FromUserName = data.FromUserName[0];
        msg.CreateTime = data.CreateTime[0];
        msg.MsgType = data.MsgType[0];

        switch (msg.MsgType) {
            case 'text':
                msg.Content = data.Content[0];
                msg.MsgId = data.MsgId[0];

                emitter.emit("text", msg);
                break;

            case 'image':
                msg.PicUrl = data.PicUrl[0];
                msg.MsgId = data.MsgId[0];
                msg.MediaId = data.MediaId[0];

                emitter.emit("image", msg);
                break;

            case 'voice':
                msg.MediaId = data.MediaId[0];
                msg.Format = data.Format[0];
                msg.MsgId = data.MsgId[0];

                emitter.emit("voice", msg);
                break;

            case 'video':
                msg.MediaId = data.MediaId[0];
                msg.ThumbMediaId = data.ThumbMediaId[0];
                msg.MsgId = data.MsgId[0];

                emitter.emit("video", msg);
                break;

            case 'location':
                msg.Location_X = data.Location_X[0];
                msg.Location_Y = data.Location_Y[0];
                msg.Scale = data.Scale[0];
                msg.Label = data.Label[0];
                msg.MsgId = data.MsgId[0];

                emitter.emit("location", msg);
                break;

            case 'link':
                msg.Title = data.Title[0];
                msg.Description = data.Description[0];
                msg.Url = data.Url[0];
                msg.MsgId = data.MsgId[0];

                emitter.emit("link", msg);
                break;

            case 'event':
                msg.Event = data.Event[0];
                if (data.EventKey)
                    msg.EventKey = data.EventKey[0];

                emitter.emit("event", msg);
                break;
        }
    });
    return msg;
}

//监听文本信息
Wechat.prototype.text = function(callback) {
    emitter.once("text", callback);
    return this;
}

//监听图片信息
Wechat.prototype.image = function(callback) {
    emitter.once("image", callback);
    return this;
}

//监听地址信息
Wechat.prototype.location = function(callback) {
    emitter.once("location", callback);
    return this;
}

//监听链接信息
Wechat.prototype.link = function(callback) {
    emitter.once("link", callback);
    return this;
}

//监听事件信息
Wechat.prototype.event = function(callback) {
    emitter.once("event", callback);
    return this;
}

//监听语音信息
Wechat.prototype.voice = function(callback) {
    emitter.once("voice", callback);
    return this;
}

//监听视频信息
Wechat.prototype.video = function(callback) {
    emitter.once("video", callback);
    return this;
}

//监听所有信息
Wechat.prototype.all = function(callback) {
    emitter.once("text", callback);
    emitter.once("image", callback);
    emitter.once("location", callback);
    emitter.once("link", callback);
    emitter.once("event", callback);
    emitter.once("voice", callback);
    emitter.once("video", callback);

    return this;
}

//将 js 组装成 xml
Wechat.prototype.toXML = function(data) {
    //自动检测 MsgType
    var MsgType = "";
    if (!data.MsgType) {
        if (data.hasOwnProperty("Content"))
            MsgType = "text";
        if (data.hasOwnProperty("MusicUrl"))
            MsgType = "music";
        if (data.hasOwnProperty("Articles"))
            MsgType = "news";
    } else {
        MsgType = data.MsgType;
    }

    var msg = "" +
        "<xml>" +
        "<ToUserName><![CDATA[" + data.ToUserName + "]]></ToUserName>" +
        "<FromUserName><![CDATA[" + data.FromUserName + "]]></FromUserName>" +
        "<CreateTime>" + Date.now() / 1000 + "</CreateTime>" +
        "<MsgType><![CDATA[" + MsgType + "]]></MsgType>";

    switch (MsgType) {
        case 'text':
            msg += "" +
                "<Content><![CDATA[" + (data.Content || '') + "]]></Content>" +
                "</xml>";
            return msg;

        case 'image':
            msg += "" +
                "<Image>" +
                "<MediaId><![CDATA[" + data.MediaId + "]]></MediaId>" +
                "</Image>" +
                "</xml>";

        case 'voice':
            msg += "" +
                "<Voice>" +
                "<MediaId><![CDATA[" + data.MediaId + "]]></MediaId>" +
                "<Title><![CDATA[" + data.Title + "]]></Title>" +
                "<Description><![CDATA[" + data.Description + "]]></Description>" +
                "</Voice>" +
                "</xml>";

        case 'video':
            msg += "" +
                "<Video>" +
                "<MediaId><![CDATA[" + data.MediaId + "]]></MediaId>" +
                "</Video>" +
                "</xml>";

        case 'music':
            msg += "" +
                "<Music>" +
                "<Title><![CDATA[" + (data.Title || '') + "]]></Title>" +
                "<Description><![CDATA[" + (data.Description || '') + "]]></Description>" +
                "<MusicUrl><![CDATA[" + (data.MusicUrl || '') + "]]></MusicUrl>" +
                "<HQMusicUrl><![CDATA[" + (data.HQMusicUrl || data.MusicUrl || '') + "]]></HQMusicUrl>" +
                "<ThumbMediaId><![CDATA[" + (data.ThumbMediaId || '') + "]]></ThumbMediaId>" +
                "</Music>" +
                "</xml>";
            return msg;

        case 'news':
            var ArticlesStr = "";
            var ArticleCount = data.Articles.length;
            for (var i in data.Articles) {
                ArticlesStr += "" +
                    "<item>" +
                    "<Title><![CDATA[" + (data.Articles[i].Title || '') + "]]></Title>" +
                    "<Description><![CDATA[" + (data.Articles[i].Description || '') + "]]></Description>" +
                    "<PicUrl><![CDATA[" + (data.Articles[i].PicUrl || '') + "]]></PicUrl>" +
                    "<Url><![CDATA[" + (data.Articles[i].Url || '') + "]]></Url>" +
                    "</item>";
            }

            msg += "<ArticleCount>" + ArticleCount + "</ArticleCount><Articles>" + ArticlesStr + "</Articles></xml>";
            return msg;
    }
}

//回复消息
Wechat.prototype.send = function(data) {
    this.res.writeHead(200, {
        'Content-Type': 'text/plain'
    });
    if (getClass(data) == 'String') {
        this.res.end(data)
    } else {
        this.res.end(this.toXML(data));
    }
    return this;
}

//获取AccessToken
Wechat.prototype.gettoken = function(resolve) {
    var promise = new Promise((resolve, reject) => {
        if (this.access_token) {
            resolve(this.access_token)
            return
        }
        var sUrl = '';
        if (this.CorpID)
            sUrl = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=' + this.CorpID + '&corpsecret=' + this.Secret;
        else if (this.AppID) {
            if (this.AppID == 'wxae9c0d778b917c56') {
                getHtml({
                    url: 'http://lngj.itiandiwechat.com.cn/xintiandi/weixin/getAccessToken/fsglb'
                }).then(result => {
                    var obj = JSON.parse(result)
                    require('../util/getHtml')({
                        url: 'http://lngj.itiandiwechat.com.cn/xintiandi/weixin/decrypt/fsglb?content=' + obj.token
                    }).then(result => {
                        this.access_token = result
                        setTimeout(() => {
                            this.access_token = ''
                            this.gettoken()
                        }, 3600000)
                        log(result)
                        resolve(result)
                    })
                })
                return
            }
            sUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + this.AppID + '&secret=' + this.AppSecret;
        } else {
            reject()
            return
        }
        var urlObj = url.parse(sUrl, true),
            options = {
                host: urlObj.hostname,
                port: urlObj.port,
                path: urlObj.pathname,
                method: 'GET'
            }
        if (urlObj.search)
            options.path += urlObj.search;
        if (!urlObj.port)
            options.port = urlObj.protocol == 'http' ? 80 : 443;
        const req = https.request(options, (res) => {
            var body = []
            res.on('data', (chunk) => {
                body.push(chunk)
            }).on('end', () => {
                var resObj = JSON.parse(Buffer.concat(body).toString());
                if (!resObj.access_token) {
                    logger.error('[' + __filename + ':' + __line + ']', JSON.stringify(resObj))
                    reject()
                } else {
                    this.access_token = resObj.access_token;
                    resolve(resObj.access_token)
                    setTimeout(() => {
                        this.access_token = ''
                        this.gettoken()
                    }, (resObj.expires_in - 60) * 1000)
                }
            }).on('error', (err) => {
                log(err)
            })
        });
        req.on('error', (err) => {
            log(err)
        })
        req.end()
    })
    if (resolve) {
        promise.then(resolve, () => {})
    } else {
        return promise
    }
}

//获取素材列表
Wechat.prototype.materialBatchget = function() {
    const urlObj = url.parse('https://qyapi.weixin.qq.com/cgi-bin/material/batchget?access_token=' + this.access_token, true),
        postData = JSON.stringify({
            type: "image",
            offset: 0,
            count: 10
        }),
        options = {
            host: urlObj.hostname,
            port: urlObj.port,
            path: urlObj.pathname,
            method: 'POST',
            headers: {
                'Content-Type': 'text/json',
                'Content-Length': Buffer.byteLength(postData)
            }
        }
    if (urlObj.search)
        options.path += urlObj.search;
    if (!urlObj.port)
        options.port = urlObj.protocol == 'http' ? 80 : 443;
    const req = https.request(options, (res) => {
        var body = []
        res.on('data', (chunk) => {
            body.push(chunk)
        }).on('end', () => {
            var resObj = JSON.parse(Buffer.concat(body).toString());
            log(resObj)
        }).on('error', (err) => {
            log(err)
        })
    });
    req.on('error', (err) => {
        log(err)
    })
    req.write(postData)
    req.end()
}

//上传临时素材文件
Wechat.prototype.mediaUpload = function(obj) {
    var sUrl = '';
    if (this.CorpID)
        sUrl = 'https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=' + this.access_token + '&type=image';
    else
        sUrl = 'https://api.weixin.qq.com/cgi-bin/media/upload?access_token=' + this.access_token + '&type=image';
    const urlObj = url.parse(sUrl, true),
        options = {
            host: urlObj.hostname,
            port: urlObj.port,
            path: urlObj.pathname,
            method: 'POST',
            protocol: 'https:'
        }
    if (urlObj.search)
        options.path += urlObj.search;
    if (!urlObj.port)
        options.port = urlObj.protocol == 'http' ? 80 : 443;
    const formDate = new FormData();
    if (obj.file)
        formDate.append('media', fs.createReadStream(obj.file));
    if (obj.fileData)
        formDate.append('media', obj.fileData);
    formDate.submit(options, (err, res) => {
        if (err) {
            log(err)
            return
        }
        var body = []
        res.on('data', (chunk) => {
            body.push(chunk)
        }).on('end', () => {
            var resObj = JSON.parse(Buffer.concat(body).toString());
            if (!resObj.media_id)
                log(resObj);
            obj.resolve(resObj.media_id)
        }).on('error', (err) => {
            log(err)
        })
    })
}

//发消息
Wechat.prototype.messageSend = function(obj) {
    if (!obj.touser) {
        log('没有touser')
        return
    }
    if (!obj.msgtype) {
        log('没有msgtype')
        return
    }
    if (!obj.media_id && !obj.content) {
        log('没有media_id和content')
        return;
    }
    obj.resolve = obj.resolve || (() => {});
    const urlObj = url.parse('https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + this.access_token, true),
        postObj = {
            touser: obj.touser,
            //toparty : '',
            //totag : '',
            agentid: 9,
            safe: 0
        }
    postObj.msgtype = obj.msgtype;
    if (postObj.msgtype == 'text') {
        postObj.text = {
            content: obj.content
        }
    } else if (postObj.msgtype == 'image') {
        postObj.image = {
            media_id: obj.media_id
        }
    }
    const postData = JSON.stringify(postObj),
        options = {
            host: urlObj.hostname,
            port: urlObj.port,
            path: urlObj.pathname,
            method: 'POST',
            headers: {
                'Content-Type': 'text/json',
                'Content-Length': Buffer.byteLength(postData)
            }
        }
    if (urlObj.search)
        options.path += urlObj.search;
    if (!urlObj.port)
        options.port = urlObj.protocol == 'http' ? 80 : 443;
    const req = https.request(options, (res) => {
        var body = []
        res.on('data', (chunk) => {
            body.push(chunk)
        }).on('end', () => {
            var resObj = JSON.parse(Buffer.concat(body).toString());
            if (resObj.errcode != 0)
                log(resObj);
            obj.resolve()
        }).on('error', (err) => {
            log(err)
        })
    });
    req.on('error', (err) => {
        log(err)
    })
    req.write(postData)
    req.end()
}

//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296
Wechat.prototype.menuCreate = function() {
    return new Promise((resolve, reject) => {
        this.gettoken().then(result => {
            getHtml({
                url: 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' + result,
                data: JSON.stringify({
                    button: [
                        /*{
                                        name: '了解住宅',
                                        sub_button: [{
                                            type: 'view',
                                            name: '关于瑞安',
                                            url: 'http://mp.weixin.qq.com/s?__biz=MzA3MDYzNzEyNw==&mid=504654323&idx=1&sn=ad75f2cf51e73a9c859451ab71ed3037&chksm=04d90adb33ae83cd309a878fd0100c1167bcb106e78e26368e7267c6ef865eef8cbb56018332&scene=18#wechat_redirect'
                                        }, {
                                            type: 'view',
                                            name: '璟廷微楼书',
                                            url: 'http://wx.wevein.com/app/index.php?i=1&c=entry&do=display&m=cj_sol_story'
                                        }, {
                                            type: 'view',
                                            name: '项目资讯',
                                            url: 'http://mp.weixin.qq.com/mp/homepage?__biz=MzA3MDYzNzEyNw==&hid=1&sn=d9bc05a89ba70b2cf7cd4f360d1f55e6&scene=18#wechat_redirect'
                                        }, {
                                            type: 'view',
                                            name: '璟轩',
                                            url: 'http://720yun.com/t/98a2b9s6y4r?from=singlemessage&isappinstalled=0&pano_id=1510981'
                                        }, {
                                            type: 'view',
                                            name: '销售导航',
                                            url: 'http://wxx.weeton.cn/v/U805J35882'
                                        }]
                                    }, {
                                        name: '专享定制',
                                        sub_button: [{
                                            type: 'click',
                                            name: '在线选房',
                                            key: '14'
                                        }, {
                                            type: 'miniprogram',//'click',
                                            name: '业主福利',
                                            //key: '10',
                                            appid: 'wx9725aecca23583dd',
                                            pagepath: 'pages/index/index',
                                            url: 'http://mp.weixin.qq.com/s?__biz=MzA3MDYzNzEyNw==&mid=504654323&idx=1&sn=ad75f2cf51e73a9c859451ab71ed3037&chksm=04d90adb33ae83cd309a878fd0100c1167bcb106e78e26368e7267c6ef865eef8cbb56018332&scene=18#wechat_redirect',
                                        }, {
                                            type: 'view',
                                            name: '定制介绍',
                                            url: 'http://mp.weixin.qq.com/s?__biz=MzA3MDYzNzEyNw==&mid=504654318&idx=1&sn=d6fbba13f5a1e747017d14b7fb5ecd00&chksm=04d90ac633ae83d0a50150967240ff582f1d30fdd70824486a9156d8a9b8d9f6c4fddf1291b8&scene=18#wechat_redirect'
                                        }, {
                                            type: 'click',
                                            name: '在线服务',
                                            key: '12'
                                        }, {
                                            type: 'click',
                                            name: '400热线',
                                            key: '13'
                                        }]
                                    }, {
                                        name: 'i天地',
                                        sub_button: [{
                                            type: 'view',
                                            name: '手机绑定',
                                            url: 'http://lngj.itiandiwechat.com.cn/xintiandi/wxutil/welcome/9/2'
                                        }, {
                                            type: 'view',
                                            name: '会员卡',
                                            url: 'http://lngj.itiandiwechat.com.cn/xintiandi/wxutil/welcome/9/3'
                                        }, {
                                            type: 'view',
                                            name: '折扣优惠券',
                                            url: 'http://lngj.itiandiwechat.com.cn/xintiandi/wxutil/welcome/9/4'
                                        }, {
                                            type: 'view',
                                            name: '优惠商户',
                                            url: 'http://lngj.itiandiwechat.com.cn/xintiandi/wxutil/welcome/9/6'
                                        }, {
                                            type: 'view',
                                            name: '积分补登',
                                            url: 'http://lngj.itiandiwechat.com.cn/xintiandi/wxutil/welcome/9/20'
                                        }]
                                    },*/
                        {
                            name: '个人中心',
                            sub_button: [{
                                type: 'view',
                                name: '我的订单',
                                url: 'https://etourly.com/#/bill'
                            }, {
                                type: 'view',
                                name: '绑定账户',
                                url: 'https://etourly.com/#/login'
                            }, {
                                type: 'view',
                                name: '旅悠首页',
                                url: 'https://etourly.com'
                            }]
                            // type: 'view',
                            // name: '业务内容',
                            // url: 'https://www.uupt.com/'
                        }, {
                            type: 'view',
                            name: '能源优惠',
                            url: 'https://st.czb365.com/v3_prod/?pft=98641152'
                        }, {
                            name: '使用教程',
                            sub_button: [{
                                type: 'view',
                                name: '淘宝教程',
                                url: 'https://etourly.com/%E8%BF%94%E5%88%A9%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AC%E4%BC%97%E5%8F%B7%EF%BC%89.html'
                            }, {
                                type: 'view',
                                name: '京东教程',
                                url: 'https://mp.weixin.qq.com/s/olTzu3lOwa8evOZwCGPcIw'
                            }, {
                                type: 'view',
                                name: '能源教程',
                                url: 'https://mp.weixin.qq.com/s/4aYhE9oPRjS-H15dzTUMdw'
                            }]
                            // type: 'view',
                            // name: '配送服务',
                            // url: 'https://theflowerhome.cn/'
                        }
                    ]
                }),
                headers: {
                    'Content-Type': 'text/json'
                }
            }).then(result => {
                resolve(JSON.parse(result))
            }, result => {
                if (result)
                    logger.error('[' + __filename + ':' + __line + ']', result)
                reject(result)
            })
        }, result => {
            if (result)
                logger.error('[' + __filename + ':' + __line + ']', result)
            reject(result)
        })
    })
}

//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025272
Wechat.prototype.cardBatchget = function(obj) {
    return new Promise((resolve, reject) => {
        if (!obj.offset) {
            reject('没有offset')
            return
        }
        if (!obj.count) {
            reject('没有count')
            return
        }
        if (!obj.status_list) {
            reject('没有status_list')
            return
        }
        getHtml({
            url: 'https://api.weixin.qq.com/card/batchget?access_token=' + this.access_token,
            data: JSON.stringify(obj),
            headers: {
                'Content-Type': 'text/json'
            }
        }).then(result => {
            resolve(JSON.parse(result))
        }, result => {
            reject(result)
        })
    })
}

//https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject
Wechat.prototype.snsJscode2session = function(obj) {
    return new Promise((resolve, reject) => {
        if (!obj.js_code) {
            reject('没有js_code')
            return
        }
        getHtml({
            url: 'https://api.weixin.qq.com/sns/jscode2session?appid=' + this.AppID + '&secret=' + this.AppSecret + '&js_code=' + obj.js_code + '&grant_type=authorization_code',
            headers: {
                'Content-Type': 'text/json'
            }
        }).then(result => {
            resolve(JSON.parse(result))
        }, result => {
            reject(result)
        })
    })
}

//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1496561749_f7T6D
Wechat.prototype.ticketGetticket = function() {
    return new Promise((resolve, reject) => {
        getHtml({
            url: 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card&access_token=' + this.access_token,
            headers: {
                'Content-Type': 'text/json'
            }
        }).then(result => {
            resolve(JSON.parse(result))
        }, result => {
            reject(result)
        })
    })
}

//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025272
Wechat.prototype.cardUserGetcardlist = function(obj) {
    return new Promise((resolve, reject) => {
        if (!obj.openid) {
            reject('缺少openid')
            return
        }
        getHtml({
            url: 'https://api.weixin.qq.com/card/user/getcardlist?access_token=' + this.access_token,
            data: JSON.stringify(obj),
            headers: {
                'Content-Type': 'text/json'
            }
        }).then(result => {
            resolve(JSON.parse(result))
        }, result => {
            reject(result)
        })
    })
}

// https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025272
Wechat.prototype.cardGet = function(obj) {
    return new Promise((resolve, reject) => {
        if (!obj.card_id) {
            reject('缺少card_id')
            return
        }
        getHtml({
            url: 'https://api.weixin.qq.com/card/get?access_token=' + this.access_token,
            data: JSON.stringify(obj),
            headers: {
                'Content-Type': 'text/json'
            }
        }).then(result => {
            resolve(JSON.parse(result))
        }, result => {
            reject(result)
        })
    })
}

// https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025239
Wechat.prototype.cardCodeDecrypt = function(obj) {
    return new Promise((resolve, reject) => {
        if (!obj.encrypt_code) {
            reject('缺少encrypt_code')
            return
        }
        getHtml({
            url: 'https://api.weixin.qq.com/card/code/decrypt?access_token=' + this.access_token,
            data: JSON.stringify(obj),
            headers: {
                'Content-Type': 'text/json'
            }
        }).then(result => {
            resolve(JSON.parse(result))
        }, result => {
            reject(result)
        })
    })
}

//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547
Wechat.prototype.messageCustomSend = function(obj) {
    return new Promise((resolve, reject) => {
        if (!obj.touser) {
            logger.debug('[' + __filename + ':' + __line + '] 没有touser')
            reject()
            return
        }
        if (!obj.msgtype) {
            logger.debug('[' + __filename + ':' + __line + '] 没有msgtype')
            reject()
            return
        }
        if (!obj.media_id && !obj.content) {
            logger.debug('[' + __filename + ':' + __line + '] 没有media_id和content')
            reject()
            return
        }
        var postObj = {
            touser: obj.touser,
            msgtype: obj.msgtype,
        }
        if (postObj.msgtype == 'text') {
            postObj.text = {
                content: obj.content
            }
        } else if (postObj.msgtype == 'image') {
            postObj.image = {
                media_id: obj.media_id
            }
        }
        this.gettoken().then(result => {
            var url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=' + result
            getHtml({
                url,
                data: JSON.stringify(postObj),
                headers: {
                    'Content-Type': 'text/json'
                }
            }).then(result => {
                var obj = JSON.parse(result)
                if (obj.errcode) {
                    logger.error('[' + __filename + ':' + __line + ']', url, result)
                    reject(obj)
                } else {
                    resolve(obj)
                }
            }, result => {
                logger.error('[' + __filename + ':' + __line + ']', url, result)
                reject(result)
            })
        })
    })
}

//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
Wechat.prototype.snsOauth2AccessToken = function(obj) {
    return new Promise((resolve, reject) => {
        if (!obj.code) {
            reject('没有code')
            return
        }
        getHtml({
            url: 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' + this.AppID + '&secret=' + this.AppSecret + '&code=' + obj.code + '&grant_type=authorization_code',
            headers: {
                'Content-Type': 'text/json'
            }
        }).then(result => {
            resolve(JSON.parse(result))
        }, result => {
            reject(result)
        })
    })
}

//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542
Wechat.prototype.qrcodeCreate = function(obj) {
    return new Promise((resolve, reject) => {
        if (!obj.scene_id) {
            reject('没有scene_id')
            return
        }
        this.gettoken(result => {
            getHtml({
                url: 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=' + result,
                headers: {
                    'Content-Type': 'text/json'
                },
                data: JSON.stringify({
                    action_name: 'QR_LIMIT_SCENE',
                    action_info: {
                        scene: {
                            scene_id: obj.scene_id
                        }
                    }
                })
            }).then(result => {
                var obj = JSON.parse(result)
                if (obj.errcode) {
                    logger.error('[' + __filename + ':' + __line + ']', result)
                    reject(obj)
                } else {
                    resolve(obj)
                }
            }, result => {
                logger.error('[' + __filename + ':' + __line + ']', result)
                reject(result)
            })
        })
    })
}

module.exports = Wechat;